const express = require("express");
const { Sequelize, DataTypes, Op } = require("sequelize");

// / 方法 2: 分别传递参数 (sqlite)
const sequelize = new Sequelize({
  dialect: "sqlite",
  // 改成自己项目中数据库文件--（这个文件不用自己创建-否则会报错）
  storage: "./db/mydb.sqlite",
});

// const sequelize = new Sequelize("sqlite::memory:"); // Sqlite 示例

async function loginDb() {
  try {
    await sequelize.authenticate();
    console.log("链接数据库成功");
  } catch (error) {
    console.error("不能数据连接到数据:", error);
  }
}
loginDb();

// 创建用户表
const User = sequelize.define(
  "User",
  {
    // 表中会自动生成id字段

    // 在这里定义模型属性
    // 定义表中表头-字段-name
    username: {
      // 类型为字符串
      type: DataTypes.STRING,
    },
    email: {
      type: DataTypes.STRING,
      // allowNull 默认为 true
    },
    password: {
      type: DataTypes.STRING,
      // allowNull 默认为 true
    },
  },
)

// 调用 express函数-可以创建一个服务器（后端程序）对象
const app = express();

// 设置允许跨域
app.use(function (req, res, next) {
  //设置允许跨域的域名，*代表允许任意域名跨域
  res.header("Access-Control-Allow-Origin", "*");
  //允许的header类型， content-type
  res.header("Access-Control-Allow-Headers", "*");
  //跨域允许的请求方式
  res.header(
    "Access-Control-Allow-Methods",
    "DELETE,PUT,POST,GET,OPTIONS,PATCH"
  );
  next();
});

// ***解析前端的请求体-json解析
app.use(express.json());

// 后端的端口号
const port = 3000;

/*
  1-
  给用户列表查询接口，添加分页功能
  
  2-
  给用户列表查询接口，添加搜索功能
  
  3-
  给用户列表查询接口，添加排序功能
  

*/
app.get("/users", async (req, res) => {
  console.log("获取所有用户列表");
  console.log("查询参数:", req.query);

  // 获取查询参数
  const {
    page = 1, // 当前页码，默认第1页
    pageSize = 10, // 每页数据条数，默认10条
    search = "", // 搜索关键字
    sortBy = "id", // 排序字段，默认按id排序
    sortOrder = "ASC", // 排序方式，默认升序ASC，可选DESC
  } = req.query;

  // 转换数据类型
  const currentPage = parseInt(page);
  const limit = parseInt(pageSize);
  const offset = (currentPage - 1) * limit;

  // 构建查询条件
  const whereCondition = {};

  // 如果有搜索关键字，添加搜索条件
  if (search) {
    whereCondition[Op.or] = [
      { username: { [Op.like]: `%${search}%` } },
      { email: { [Op.like]: `%${search}%` } },
    ];
  }

  // 构建排序条件
  const orderCondition = [[sortBy, sortOrder.toUpperCase()]];

  try {
    // 查询用户数据（带分页、搜索、排序）
    const { count, rows } = await User.findAndCountAll({
      where: whereCondition,
      limit: limit,
      offset: offset,
      order: orderCondition,
    });

    // 计算总页数
    const totalPages = Math.ceil(count / limit);

    res.json({
      code: 1,
      message: "获取用户列表成功",
      data: {
        users: rows, // 用户数据
        pagination: {
          currentPage: currentPage, // 当前页码
          pageSize: limit, // 每页数据条数
          totalRecords: count, // 总记录数
          totalPages: totalPages, // 总页数
          hasNext: currentPage < totalPages, // 是否有下一页
          hasPrev: currentPage > 1, // 是否有上一页
        },
        search: search, // 搜索关键字
        sort: {
          sortBy: sortBy, // 排序字段
          sortOrder: sortOrder, // 排序方式
        },
      },
    });
  } catch (error) {
    console.error("查询用户列表失败:", error);
    res.json({
      code: 0,
      message: "查询用户列表失败",
      error: error.message,
    });
  }
});

// 获取特定用户 - GET请求
app.get("/users/:id", (req, res) => {
  console.log("获取用户ID:", req.params.id);
  // 这里应该从数据库根据ID获取用户数据
  res.json({
    code: 1,
    message: "获取用户信息成功",
    data: {
      id: req.params.id,
      // 其他用户信息
    },
  });
});

// 创建新用户 - POST请求
app.post("/users", async (req, res) => {
  console.log("创建新用户:", req.body);
  // 获取请求体中的用户信息
  let { username, email, password } = req.body;
  console.log("用户名:", username, "邮箱:", email, password);

  // 这里应该进行数据验证和保存到数据库
  if (username && password) {
  } else {
    res.json({
      code: 0,
      message: "户名名或者密码为null",
      data: {},
    });
    return;
  }

  // 保存到数据库
  // let userObj = User.build({
  //   username: username,
  //   password: password,
  //   email: email,
  // });
  // //保存数据到数据库
  // await userObj.save();

  //返回创建好的数据数据
  const jane = await User.create({
    username: username,
    password: password,
    email: email,
  });
  console.log(jane);

  res.json({
    code: 1,
    message: "用户创建成功",
    data: jane,
  });
});

// 修改用户信息 - PATCH请求
app.patch("/users/:id", async (req, res) => {
  console.log("修改用户ID:", req.params.id);
  console.log("修改内容:", req.body);

  // 获取要修改的用户信息
  let { username, email, password } = req.body;

  // 根据id，更新用户信息
  await User.update(
    // { lastName: "Doe" },
    req.body,
    // 查询条件
    {
      where: {
        id: req.params.id,
      },
    }
  );

  // 这里应该根据ID在数据库中更新用户信息
  res.json({
    code: 1,
    message: "用户信息修改成功",
    // data: u,
  });
});

// 删除用户 - DELETE请求
app.delete("/users/:id", async (req, res) => {
  console.log("删除用户ID:", req.params.id);

  // 这里应该从数据库中删除对应ID的用户

  // 先根据主键（id）找到这个用户，然后删除
  let u = await User.findByPk(req.params.id);
  await u.destroy();

  res.json({
    code: 1,
    message: "用户删除成功",
  });
});

/*
  仿照/users的增删改查接口，编写一个/商品的增删改查接口
  商品表：
  id
  name
  price
  stock
  description
  imageUrl
*/

// 获取所有商品 - GET请求 (支持分页、搜索、排序)
app.get("/products", async (req, res) => {
  console.log("获取所有商品列表");
  console.log("查询参数:", req.query);

  // 获取查询参数
  const {
    page = 1, // 当前页码，默认第1页
    pageSize = 10, // 每页数据条数，默认10条
    search = "", // 搜索关键字
    sortBy = "id", // 排序字段，默认按id排序
    sortOrder = "ASC", // 排序方式，默认升序ASC，可选DESC
  } = req.query;

  // 转换数据类型
  const currentPage = parseInt(page);
  const limit = parseInt(pageSize);
  const offset = (currentPage - 1) * limit;

  // 构建查询条件
  const whereCondition = {};

  // 如果有搜索关键字，添加搜索条件
  if (search) {
    whereCondition[Op.or] = [
      { name: { [Op.like]: `%${search}%` } },
      { description: { [Op.like]: `%${search}%` } },
    ];
  }

  // 构建排序条件
  const orderCondition = [[sortBy, sortOrder.toUpperCase()]];

  try {
    // 查询商品数据（带分页、搜索、排序）
    const { count, rows } = await Product.findAndCountAll({
      where: whereCondition,
      limit: limit,
      offset: offset,
      order: orderCondition,
    });

    // 计算总页数
    const totalPages = Math.ceil(count / limit);

    res.json({
      code: 1,
      message: "获取商品列表成功",
      data: {
        products: rows, // 商品数据
        pagination: {
          currentPage: currentPage, // 当前页码
          pageSize: limit, // 每页数据条数
          totalRecords: count, // 总记录数
          totalPages: totalPages, // 总页数
          hasNext: currentPage < totalPages, // 是否有下一页
          hasPrev: currentPage > 1, // 是否有上一页
        },
        search: search, // 搜索关键字
        sort: {
          sortBy: sortBy, // 排序字段
          sortOrder: sortOrder, // 排序方式
        },
      },
    });
  } catch (error) {
    console.error("查询商品列表失败:", error);
    res.json({
      code: 0,
      message: "查询商品列表失败",
      error: error.message,
    });
  }
});

// 获取特定商品 - GET请求
app.get("/products/:id", async (req, res) => {
  console.log("获取商品ID:", req.params.id);

  try {
    // 根据ID查询商品数据
    const product = await Product.findByPk(req.params.id);

    if (product) {
      res.json({
        code: 1,
        message: "获取商品信息成功",
        data: product,
      });
    } else {
      res.json({
        code: 0,
        message: "商品不存在",
      });
    }
  } catch (error) {
    console.error("查询商品失败:", error);
    res.json({
      code: 0,
      message: "查询商品失败",
      error: error.message,
    });
  }
});

// 创建新商品 - POST请求
app.post("/products", async (req, res) => {
  console.log("创建新商品:", req.body);

  // 获取请求体中的商品信息
  let { name, price, stock, description, imageUrl } = req.body;
  console.log("商品名称:", name, "价格:", price, "库存:", stock);

  // 数据验证
  if (!name || !price) {
    res.json({
      code: 0,
      message: "商品名称和价格不能为空",
      data: {},
    });
    return;
  }

  try {
    // 创建商品并保存到数据库
    const product = await Product.create({
      name: name,
      price: price,
      stock: stock || 0,
      description: description,
      imageUrl: imageUrl,
    });

    console.log("创建的商品:", product);

    res.json({
      code: 1,
      message: "商品创建成功",
      data: product,
    });
  } catch (error) {
    console.error("创建商品失败:", error);
    res.json({
      code: 0,
      message: "创建商品失败",
      error: error.message,
    });
  }
});

// 修改商品信息 - PATCH请求
app.patch("/products/:id", async (req, res) => {
  console.log("修改商品ID:", req.params.id);
  console.log("修改内容:", req.body);

  try {
    // 根据id，更新商品信息
    const [updatedRowsCount] = await Product.update(req.body, {
      where: {
        id: req.params.id,
      },
    });

    if (updatedRowsCount > 0) {
      // 获取更新后的商品信息
      const updatedProduct = await Product.findByPk(req.params.id);

      res.json({
        code: 1,
        message: "商品信息修改成功",
        data: updatedProduct,
      });
    } else {
      res.json({
        code: 0,
        message: "商品不存在或修改失败",
      });
    }
  } catch (error) {
    console.error("修改商品失败:", error);
    res.json({
      code: 0,
      message: "修改商品失败",
      error: error.message,
    });
  }
});

// 删除商品 - DELETE请求
app.delete("/products/:id", async (req, res) => {
  console.log("删除商品ID:", req.params.id);

  try {
    // 先根据主键（id）找到这个商品，然后删除
    const product = await Product.findByPk(req.params.id);

    if (product) {
      await product.destroy();
      res.json({
        code: 1,
        message: "商品删除成功",
      });
    } else {
      res.json({
        code: 0,
        message: "商品不存在",
      });
    }
  } catch (error) {
    console.error("删除商品失败:", error);
    res.json({
      code: 0,
      message: "删除商品失败",
      error: error.message,
    });
  }
});

// 启动服务器-监听了3000端口
app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});

// 本地的3000端口就是 这个后端程序（服务器）的接口地址
// http://localhost:3000
// http://127.0.0.1:3000 （自己电脑上有效）
// http://192.168.12.46:3000  (内网-局域网内有效)
